<template>
  <div
    class="el-input-tag input-tag-wrapper"
    :class="[size ? `el-input-tag--${size}` : '']"
    @click="focusTagInput"
  >
    <el-tag
      v-for="(tag, idx) in innerTags"
      v-bind="$attrs"
      :key="tag"
      :size="size"
      effect="dark"
      :disable-transitions="false"
    >
      {{ tag }}
    </el-tag>

    <input
      v-if="!readOnly"
      class="tag-input"
      :placeholder="placeholder"
      @input="inputTag"
      :value="newTag"
      @keydown.delete.stop="removeLastTag"
      @keydown.enter="addNew"
      @blur="addNew"
      ref="inputElement"
    />
  </div>
</template>

<script setup>
import { ref, watch } from "vue";
import { StrUtil } from "@/utils/StrUtil";


// 定义组件的 props
const props = defineProps({
  modelValue: {
    type: String,
    default: "",
  },
  addTagOnKeys: {
    type: Array,
    default: () => [],
  },
  size: {
    type: String,
    default: "small",
  },
  placeholder: String,
  readOnly: {
    type: Boolean,
    default: true,
  },
});

// 定义事件
const emit = defineEmits(["update:modelValue"]);

// 定义响应式数据
const newTag = ref("");
const innerTags = ref([]);
const inputElement = ref(null);

// 监听 modelValue 的变化
watch(
  () => props.modelValue,
  (newVal) => {
    if (StrUtil.isNotBlank(newVal)) {
      innerTags.value = newVal.split(",");
    } else {
      innerTags.value = [];
    }
  },
  { immediate: true }
);

// 方法定义
const focusTagInput = () => {
  if (props.readOnly || !inputElement.value) {
    return;
  }
  inputElement.value.focus();
};

const inputTag = (event) => {
  newTag.value = event.target.value;
};

const addNew = (event) => {
  if (
    event &&
    !props.addTagOnKeys.includes(event.keyCode) &&
    event.type !== "blur"
  ) {
    return;
  }
  if (event) {
    event.stopPropagation();
    event.preventDefault();
  }
  let addSuccess = false;
  if (newTag.value.includes(",")) {
    newTag.value.split(",").forEach((item) => {
      if (addTag(item.trim())) {
        addSuccess = true;
      }
    });
  } else {
    if (addTag(newTag.value.trim())) {
      addSuccess = true;
    }
  }
  if (addSuccess) {
    tagChange();
    newTag.value = "";
  }
};

const addTag = (tag) => {
  tag = tag.trim();
  if (tag && !innerTags.value.includes(tag)) {
    innerTags.value.push(tag);
    return true;
  }
  return false;
};

const remove = (index) => {
  innerTags.value.splice(index, 1);

  tagChange();
};

const removeLastTag = () => {
  if (newTag.value) {
    return;
  }
  innerTags.value.pop();
  tagChange();
};

const tagChange = () => {
  emit("update:modelValue", innerTags.value.join(","));
};




// 暴露方法供父组件调用
defineExpose({
  focusTagInput,
});
</script>

<style scoped>
.el-form-item.is-error .el-input-tag {
  border-color: #f56c6c;
}
.input-tag-wrapper {
  position: relative;
  font-size: 14px;
  background-color: #fff;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  color: #606266;
  display: inline-block;
  outline: none;
  padding: 0 10px 0 5px;
  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
  width: 100%;
}
.el-tag {
  margin-right: 4px;
}

.tag-input {
  background: transparent;
  border: 0;
  font-size: inherit;
  outline: none;
  padding-left: 0;
  width: 100px;
}
.el-input-tag {
  min-height: 42px;
}
.el-input-tag--small {
  min-height: 32px;
  line-height: 32px;
  font-size: 12px;
}

.el-input-tag--default {
  min-height: 34px;
  line-height: 34px;
}

.el-input-tag--large {
  min-height: 36px;
  line-height: 36px;
}
</style>
